package cn.lblbc.appassit.utils

import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import cn.lblbc.appassit.model.AppInfo

private const val TAG = "AppScannerPerf"

class AppScanner(private val context: Context) {
    
    private val packageManager = context.packageManager
    
    fun scanInstalledApps(includeSystemApps: Boolean = false): List<AppInfo> {
        return try {
            val startTime = System.currentTimeMillis()
            Log.d(TAG, "开始扫描应用列表，includeSystemApps=$includeSystemApps")
            
            val getPackagesStart = System.currentTimeMillis()
            val installedPackages = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                // Android 11+ 需要 QUERY_ALL_PACKAGES 权限
                packageManager.getInstalledPackages(PackageManager.GET_META_DATA)
            } else {
                packageManager.getInstalledPackages(PackageManager.GET_META_DATA)
            }
            Log.d(TAG, "获取已安装包列表耗时: ${System.currentTimeMillis() - getPackagesStart}ms, 共${installedPackages.size}个包")
            
            val appInfoList = mutableListOf<AppInfo>()
            val processAppsStart = System.currentTimeMillis()
            
            var systemAppCount = 0
            var userAppCount = 0
            var skippedCount = 0
            
            for (packageInfo in installedPackages) {
                try {
                    val applicationInfo = packageInfo.applicationInfo
                    
                    // 跳过当前应用本身（可选）
                    if (packageInfo.packageName == context.packageName) {
                        skippedCount++
                        continue
                    }
                    
                    // 过滤系统应用
                    val isSystem = isSystemApp(applicationInfo)
                    if (!includeSystemApps && isSystem) {
                        skippedCount++
                        continue
                    }
                    
                    val createInfoStart = System.currentTimeMillis()
                    val appInfo = createBasicAppInfo(packageInfo, applicationInfo)
                    appInfoList.add(appInfo)
                    
                    if (isSystem) systemAppCount++ else userAppCount++
                    
                    // 记录创建单个应用信息的耗时，如果超过阈值则报警
                    val createInfoTime = System.currentTimeMillis() - createInfoStart
                    if (createInfoTime > 10) {
                        Log.w(TAG, "创建应用信息耗时过长($createInfoTime ms): ${packageInfo.packageName}")
                    }
                } catch (e: Exception) {
                    // 忽略无法获取信息的应用，但记录日志
                    Log.w("AppScanner", "Failed to get basic info for ${packageInfo.packageName}: ${e.message}")
                    skippedCount++
                    continue
                }
            }
            Log.d(TAG, "处理应用信息耗时: ${System.currentTimeMillis() - processAppsStart}ms, 系统应用${systemAppCount}个, 用户应用${userAppCount}个, 跳过${skippedCount}个")
            
            // 对列表进行一次排序，避免在UI层重复排序
            val sortStart = System.currentTimeMillis()
            appInfoList.sortWith {
                app1, app2 ->
                PinyinUtils.compareWithPinyin(app1.appName, app2.appName)
            }
            Log.d(TAG, "排序应用列表耗时: ${System.currentTimeMillis() - sortStart}ms")
            
            Log.d(TAG, "扫描应用列表完成，总耗时: ${System.currentTimeMillis() - startTime}ms, 返回${appInfoList.size}个应用")
            appInfoList
        } catch (e: SecurityException) {
            // 权限不足
            Log.e("AppScanner", "Permission denied: ${e.message}")
            throw SecurityException("需要QUERY_ALL_PACKAGES权限来获取所有应用信息")
        } catch (e: Exception) {
            Log.e("AppScanner", "Failed to scan apps: ${e.message}")
            throw e
        }
    }
    
    /**
     * 创建基本的AppInfo对象，只包含列表展示所需的信息
     * 优化性能，减少不必要的计算和文件操作
     */
    private fun createBasicAppInfo(packageInfo: PackageInfo, applicationInfo: ApplicationInfo): AppInfo {
        // 只获取列表展示必须的基本信息
        val appName = packageManager.getApplicationLabel(applicationInfo).toString()
        val packageName = packageInfo.packageName
        
        // 获取图标（列表需要显示）
        // 优化：使用弱引用或LRU缓存来减少重复加载图标的开销
        val icon = try {
            // 这个操作可能比较耗时，特别是在大量应用时
            packageManager.getApplicationIcon(applicationInfo)
        } catch (e: Exception) {
            null
        }
        
        // 判断是否为系统应用（列表需要显示系统应用标识）
        val isSystemApp = isSystemApp(applicationInfo)
        
        // 其他字段提供默认值，不进行耗时操作
        return AppInfo(
            appName = appName,
            packageName = packageName,
            versionName = "", // 列表不需要显示
            versionCode = 0L, // 列表不需要显示
            icon = icon,
            apkPath = applicationInfo.sourceDir, // 虽然列表不显示，但为了后续详情查看需要保留
            installTime = 0L, // 延迟加载
            updateTime = 0L, // 延迟加载
            isSystemApp = isSystemApp,
            targetSdkVersion = 0, // 延迟加载
            minSdkVersion = 0, // 延迟加载
            apkSize = 0L, // 延迟加载
            supports32Bit = false, // 延迟加载
            supports64Bit = false, // 延迟加载
            signatureInfo = null // 延迟加载
        )
    }
    
    /**
     * 获取应用的完整详细信息，用于应用详情页面
     * 此方法会执行所有耗时操作
     */
    fun getAppDetailedInfo(packageName: String): AppInfo? {
        try {
            val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                packageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA)
            } else {
                @Suppress("DEPRECATION")
                packageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA)
            }
            
            val applicationInfo = packageInfo.applicationInfo
            
            // 先获取基本信息
            val appName = packageManager.getApplicationLabel(applicationInfo).toString()
            val versionName = packageInfo.versionName ?: "未知"
            val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                packageInfo.longVersionCode
            } else {
                @Suppress("DEPRECATION")
                packageInfo.versionCode.toLong()
            }
            
            val icon = try {
                packageManager.getApplicationIcon(applicationInfo)
            } catch (e: Exception) {
                null
            }
            
            val apkPath = applicationInfo.sourceDir
            val installTime = packageInfo.firstInstallTime
            val updateTime = packageInfo.lastUpdateTime
            val isSystemApp = isSystemApp(applicationInfo)
            val targetSdkVersion = applicationInfo.targetSdkVersion
            val minSdkVersion = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                applicationInfo.minSdkVersion
            } else {
                0
            }
            
            // 获取APK大小（文件操作，耗时）
            val apkSize = try {
                java.io.File(apkPath).length()
            } catch (e: Exception) {
                0L
            }
            
            // 检测32位和64位支持（文件操作，耗时）
            val (supports32Bit, supports64Bit) = checkAbiSupport(applicationInfo)
            
            // 获取应用签名信息（加密计算，耗时）
            val signatureInfo = getSignatureInfo(packageInfo)
            
            return AppInfo(
                appName = appName,
                packageName = packageName,
                versionName = versionName,
                versionCode = versionCode,
                icon = icon,
                apkPath = apkPath,
                installTime = installTime,
                updateTime = updateTime,
                isSystemApp = isSystemApp,
                targetSdkVersion = targetSdkVersion,
                minSdkVersion = minSdkVersion,
                apkSize = apkSize,
                supports32Bit = supports32Bit,
                supports64Bit = supports64Bit,
                signatureInfo = signatureInfo
            )
        } catch (e: Exception) {
            android.util.Log.w("AppScanner", "Failed to get detailed info for $packageName: ${e.message}")
            return null
        }
    }
    
    private fun isSystemApp(applicationInfo: ApplicationInfo): Boolean {
        return (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0
    }
    
    private fun checkAbiSupport(applicationInfo: ApplicationInfo): Pair<Boolean, Boolean> {
        // 检查原生库目录
        val nativeLibraryDir = applicationInfo.nativeLibraryDir
        val libDir = java.io.File(nativeLibraryDir)
        
        // 如果原生库目录为空或不存在，则表示应用同时支持32位和64位
        if (!libDir.exists() || !libDir.isDirectory || libDir.listFiles()?.isEmpty() != false) {
            return Pair(true, true)
        }
        
        // 检查原生库文件以确定支持的架构
        var supports32Bit = false
        var supports64Bit = false
        
        libDir.listFiles()?.forEach { file ->
            if (file.name.endsWith(".so")) {
                // 检查文件名中的架构标识
                when {
                    file.name.contains("arm64") || file.name.contains("x86_64") || file.name.contains("mips64") -> {
                        supports64Bit = true
                    }
                    file.name.contains("armeabi") || file.name.contains("x86") || file.name.contains("mips") -> {
                        supports32Bit = true
                    }
                }
            }
        }
        
        // 如果没有检测到明确的架构，默认同时支持32位和64位
        if (!supports32Bit && !supports64Bit) {
            return Pair(true, true)
        }
        
        return Pair(supports32Bit, supports64Bit)
    }
    
    private fun getSignatureInfo(packageInfo: PackageInfo): String? {
        return try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                // Android 9.0+ 使用新的API
                val signingInfo = packageInfo.signingInfo
                if (signingInfo != null) {
                    val signatures = if (signingInfo.hasMultipleSigners()) {
                        signingInfo.apkContentsSigners
                    } else {
                        signingInfo.signingCertificateHistory
                    }
                    
                    if (signatures.isNotEmpty()) {
                        // 获取第一个签名证书
                        val signature = signatures[0]
                        
                        // 获取证书信息
                        val certFactory = java.security.cert.CertificateFactory.getInstance("X.509")
                        val certStream = java.io.ByteArrayInputStream(signature.toByteArray())
                        val cert = certFactory.generateCertificate(certStream) as java.security.cert.X509Certificate
                        
                        // 获取证书哈希值
                        val md5 = getCertificateHashFromBytes(cert.encoded, "MD5")
                        val sha1 = getCertificateHashFromBytes(cert.encoded, "SHA-1")
                        val sha256 = getCertificateHashFromBytes(cert.encoded, "SHA-256")
                        
                        val signatureInfo = "MD5: $md5\nSHA1: $sha1\nSHA256: $sha256"
                        return signatureInfo
                    }
                } else {
                    // 尝试直接从APK文件获取签名信息
                    return getSignatureFromApk(packageInfo.applicationInfo.sourceDir)
                }
            } else {
                // 旧版本使用已弃用的API
                @Suppress("DEPRECATION")
                val signatures = packageInfo.signatures
                if (signatures != null && signatures.isNotEmpty()) {
                    val signature = signatures[0]
                    val md5 = getCertificateHash(signature, "MD5")
                    val sha1 = getCertificateHash(signature, "SHA-1")
                    val sha256 = getCertificateHash(signature, "SHA-256")
                    
                    val signatureInfo = "MD5: $md5\nSHA1: $sha1\nSHA256: $sha256"
                    return signatureInfo
                } else {
                    // 尝试直接从APK文件获取签名信息
                    return getSignatureFromApk(packageInfo.applicationInfo.sourceDir)
                }
            }
            null
        } catch (e: Exception) {
            null
        }
    }
    
    private fun getSignatureFromApk(apkPath: String): String? {
        return try {
            val jarFile = java.util.jar.JarFile(apkPath)
            val entries = jarFile.entries()
            
            while (entries.hasMoreElements()) {
                val entry = entries.nextElement()
                if (entry.name.uppercase().endsWith(".RSA") || 
                    entry.name.uppercase().endsWith(".DSA") || 
                    entry.name.uppercase().endsWith(".EC")) {
                    val inputStream = jarFile.getInputStream(entry)
                    val certFactory = java.security.cert.CertificateFactory.getInstance("X.509")
                    val certStream = java.io.ByteArrayInputStream(inputStream.readBytes())
                    val cert = certFactory.generateCertificate(certStream) as java.security.cert.X509Certificate
                    
                    // 获取证书哈希值
                    val md5 = getCertificateHashFromBytes(cert.encoded, "MD5")
                    val sha1 = getCertificateHashFromBytes(cert.encoded, "SHA-1")
                    val sha256 = getCertificateHashFromBytes(cert.encoded, "SHA-256")
                    
                    val signatureInfo = "MD5: $md5\nSHA1: $sha1\nSHA256: $sha256"
                    
                    jarFile.close()
                    return signatureInfo
                }
            }
            
            jarFile.close()
            null
        } catch (e: Exception) {
            null
        }
    }
    
    private fun getCertificateHashFromBytes(certBytes: ByteArray, algorithm: String): String {
        try {
            val md = java.security.MessageDigest.getInstance(algorithm)
            val digest = md.digest(certBytes)
            
            // 转换为十六进制字符串
            val hexString = StringBuilder()
            for (i in digest.indices) {
                val hex = Integer.toHexString(0xFF and digest[i].toInt())
                if (hex.length == 1) {
                    hexString.append('0')
                }
                hexString.append(hex)
                if (i > 0 && i % 2 == 1 && i < digest.size - 1) {
                    hexString.append(':')
                }
            }
            return hexString.toString().uppercase(java.util.Locale.getDefault())
        } catch (e: Exception) {
            return "未知"
        }
    }
    
    private fun getCertificateHash(signature: android.content.pm.Signature, algorithm: String): String {
        try {
            val md = java.security.MessageDigest.getInstance(algorithm)
            val digest = md.digest(signature.toByteArray())
            
            // 转换为十六进制字符串
            val hexString = StringBuilder()
            for (i in digest.indices) {
                val hex = Integer.toHexString(0xFF and digest[i].toInt())
                if (hex.length == 1) {
                    hexString.append('0')
                }
                hexString.append(hex)
                if (i > 0 && i % 2 == 1 && i < digest.size - 1) {
                    hexString.append(':')
                }
            }
            return hexString.toString().uppercase(java.util.Locale.getDefault())
        } catch (e: Exception) {
            return "未知"
        }
    }
}